# -*- coding: utf-8 -*-
import json
import logging
import datetime

from sqlalchemy import func

from common import orm
from common.recharge.model import *

from common.pay.model import Pay, PAY_STATUS
from common.account.model.account import Account

from common.admin import db as admin_db
from common.transaction.db import add_pay_success_transaction

from common.utils.db import (get_orderby,
                             parse_query_dct, paginate,
                             generate_filter, get_count)
from common.utils import id_generator
from common.utils.tz import utc_to_local, utc_to_local_str, local_now
from common.utils.respcode import StatusCode
from common.utils.decorator import sql_wrapper
from common.utils.exceptions import AuthenticateError, DataError

_LOGGER = logging.getLogger('pay')
_TRACKER = logging.getLogger('tracker')


@sql_wrapper
def get_apply(apply_id):
    return RechargeApply.query.filter(RechargeApply.id == apply_id).first()


@sql_wrapper
def get_apply_by_pay_id(pay_id):
    return RechargeApply.query.filter(RechargeApply.pay_id == pay_id).first()


@sql_wrapper
def exists_third_id(third_id):
    return RechargeApply.query.filter(RechargeApply.third_id == third_id).count()


@sql_wrapper
def get_last_recharge(user_id):
    return RechargeApply.query.filter(RechargeApply.user_id == user_id). \
        filter(RechargeApply.status == RECHARGE_STATUS.SUCC). \
        order_by(RechargeApply.updated_at.desc()).first()


@sql_wrapper
def get_applys(user_id, limit=0, offset=0):
    query = RechargeApply.query.filter(RechargeApply.user_id == user_id)
    query = query.order_by(RechargeApply.status).order_by(RechargeApply.created_at.desc())
    if limit > 0:
        query = query.limit(limit)
    if offset > 0:
        query = query.offset(offset)
    return query.all()


@sql_wrapper
def submit_apply(user_id, recharge_type, recharger_info, rechargee_info):
    try:
        recharge_apply = RechargeApply()
        recharge_apply.user_id = user_id
        recharge_apply.recharge_type = recharge_type
        recharge_apply.recharger_info = json.dumps(recharger_info, ensure_ascii=False)
        recharge_apply.rechargee_info = json.dumps(rechargee_info, ensure_ascii=False)
        recharge_apply.status = 1
        if recharge_type == RECHARGE_TYPE.ALIPAY:
            recharge_apply.third_id = recharger_info['alipay_order_id']
        else:
            recharge_apply.pay_amount = recharger_info['price']
            recharge_apply.third_id = rechargee_info.get('platform_pay_id')

        pay = Pay()
        pay.id = id_generator.generate_long_id('pay')
        pay.user_id = user_id
        pay_type = recharge_type + 100
        pay.pay_type = pay_type
        pay.status = PAY_STATUS.SUBMIT
        pay.save()
        recharge_apply.pay_id = pay.id
        recharge_apply.save()
    except Exception as e:
        _LOGGER.exception('recharge submit_apply error, %s', e)
        raise DataError('duplicate error')
    return recharge_apply


@sql_wrapper
def exist_submit_apply(user_id, recharge_type):
    return RechargeApply.query.filter(
        RechargeApply.user_id == user_id).filter(
        RechargeApply.recharge_type == recharge_type).filter(
        RechargeApply.status == RECHARGE_STATUS.ONGOING).first()


@sql_wrapper
def revert_apply(admin_id, apply_id):
    recharge_apply = RechargeApply.query.filter(RechargeApply.id == apply_id).filter(
        RechargeApply.status == RECHARGE_STATUS.ONGOING).one()
    recharge_apply.status = RECHARGE_STATUS.FAIL
    recharge_apply.admin_id = admin_id
    recharge_apply.save()


@sql_wrapper
def finish_apply(admin_id, apply_id, pay_amount, trans_id=None):
    recharge_apply = RechargeApply.query.filter(RechargeApply.id == apply_id).one()
    recharge_apply.pay_amount = pay_amount
    recharge_apply.status = RECHARGE_STATUS.SUCC
    recharge_apply.admin_id = admin_id
    recharge_apply.save(auto_commit=False)
    if trans_id:
        AlipayTrans.query.filter(AlipayTrans.id == trans_id).update({
            'status': 1,
            'updated_at': datetime.datetime.utcnow()
        })
    extend = {
        'title': u'代理充值',
        'ext': {
            'trade_status': 'success',
            'trade_no': recharge_apply.third_id,
            'total_fee': pay_amount
        }
    }
    res = add_pay_success_transaction(recharge_apply.user_id, recharge_apply.pay_id, float(pay_amount), extend)
    if res:
        _LOGGER.info('finish_apply recharge, %s, %s, %s', admin_id, apply_id, pay_amount)
        _TRACKER.info({'user_id': recharge_apply.user_id, 'type': 'recharge', 'price': pay_amount,
                       'channel': RECHARGE_TYPE.get_label(recharge_apply.recharge_type)})
        return Pay.query.filter(Pay.id == recharge_apply.pay_id).one()
    return None


@sql_wrapper
def new_alipay_trans(third_id, remark_id, trans_amount, pay_time):
    try:
        alipay_trans = AlipayTrans.query.filter(AlipayTrans.third_id == third_id).first()
        if not alipay_trans:
            alipay_trans = AlipayTrans()
            alipay_trans.third_id = third_id
            alipay_trans.remark_id = remark_id
            alipay_trans.trans_amount = trans_amount
            alipay_trans.pay_time = pay_time
            alipay_trans.status = 0
            alipay_trans.save()
    except Exception as e:
        _LOGGER.exception('recharge new_alipay_trans error, %s', e)
    return alipay_trans


@sql_wrapper
def fetch_applied_alipay():
    return RechargeApply.query.filter(RechargeApply.recharge_type == RECHARGE_TYPE.ALIPAY).filter(
        RechargeApply.status == RECHARGE_STATUS.ONGOING).all()


@sql_wrapper
def fetch_trans_by_third_id(third_id):
    return AlipayTrans.query.filter(AlipayTrans.third_id == third_id).first()


@sql_wrapper
def list_applys(query_dct):
    query = RechargeApply.query.filter(generate_filter(
        parse_query_dct(query_dct, RechargeApply), RechargeApply))
    total_count = get_count(query)
    orderby = get_orderby(query_dct.get('$orderby'), RechargeApply)
    if orderby is not None:
        query = query.order_by(orderby)
    query = paginate(query, query_dct)
    return query.all(), total_count


@sql_wrapper
def list_trans(query_dct):
    query = AlipayTrans.query.filter(generate_filter(
        parse_query_dct(query_dct, AlipayTrans), AlipayTrans))
    total_count = get_count(query)
    orderby = get_orderby(query_dct.get('$orderby'), AlipayTrans)
    if orderby is not None:
        query = query.order_by(orderby)
    query = paginate(query, query_dct)
    return query.all(), total_count


@sql_wrapper
def export_recharge_records(query_dct):
    items, _ = list_applys(query_dct)
    resp_items = []
    for item in items:
        recharge_at = utc_to_local_str(item.created_at)
        updated_at = utc_to_local_str(item.updated_at)
        recharger_info = json.loads(item.recharger_info or '{}')
        rechargee_info = json.loads(item.rechargee_info or '{}')
        if item.recharge_type == RECHARGE_TYPE.ALIPAY:
            recharger_no = recharger_info.get('alipay_order_id')
            rechargee_no = rechargee_info.get('alipay_no')
        elif item.recharge_type == RECHARGE_TYPE.BANKCARD:
            recharger_no = recharger_info.get('bank_no')
            rechargee_no = rechargee_info.get('bank_no')
        elif item.recharge_type == RECHARGE_TYPE.WECHATPAY:
            recharger_no = recharger_info.get('wechat_no')
            rechargee_no = rechargee_info.get('wechat_no')
        admin_account = admin_db.get_user(item.admin_id)
        admin_name = admin_account.nickname if admin_account else '-'
        data_row = [item.id, item.user_id, RECHARGE_TYPE.get_label(item.recharge_type),
                    RECHARGE_STATUS.get_label(item.status), item.pay_amount or 0, recharge_at, updated_at, recharger_no,
                    rechargee_no, admin_name]
        resp_items.append(data_row)
    return resp_items
